package com.desire.test;

import java.util.concurrent.TimeUnit;

/**
 * @author desire
 */
public class _47_join_yield {
    /**
     ThreadTest t1=new ThreadTest("A");
     ThreadTest t2=new ThreadTest("B");
     t1.start();
     t1.join();
     t2.start();
     先执行t1线程，再执行t2线程。
     <p>
     ThreadTest t1=new ThreadTest("A");
     ThreadTest t2=new ThreadTest("B");
     ThreadTest t3=new ThreadTest("C");
     t1.start();
     t2.start();
     t1.join();
     t3.start();
     t1线程和t2线程交替执行，当t1线程执行完后开始t3线程，执行过程中和t2没有关系
     <p>
     多次实验可以看出，主线程在t1.join()方法处停止，并需要等待A线程执行完毕后才会执行t3.start()，
     然而，并不影响B线程的执行。因此，可以得出结论，t.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒。
     并不影响同一时刻处在运行状态的其他线程。
     <p>
     thread.Join把指定的线程加入到当前线程，可以将两个交替执行的线程合并为顺序执行的线程。
     比如在线程B中调用了线程A的Join()方法，直到线程A执行完毕后，才会继续执行线程B。
     t.join();      //调用join方法，等待线程t执行完毕
     t.join(1000);  //等待 t 线程，等待时间是1000毫秒。
     <p>
     PS:join源码中，只会调用wait方法，并没有在结束时调用notify，
     这是因为线程在完成的时候会自动调用自身的notifyAll方法，来释放所有的资源和锁。
     */


    /**
     * Thread.yield()
     * 使当前线程从执行状态（运行状态）变为可执行态（就绪状态）。cpu会从众多的可执行态里选择，也就是说，
     * 当前也就是刚刚的那个线程还是有可能会被再次执行到的，并不是说一定会执行其他线程而该线程在下一次中不会执行到了。
     * <p>
     * Java线程中有一个Thread.yield( )方法，很多人翻译成线程让步。顾名思义，就是说当一个线程使用了这个方法之后，
     * 它就会把自己CPU执行的时间让掉，     ****让自己或者其它的线程运行****
     * <p>
     * 打个比方：现在有很多人在排队上厕所，好不容易轮到这个人上厕所了，突然这个人说：“我要和大家个竞赛，看谁先抢到厕所！”，
     * 然后所有的人在同一起跑线冲向厕所，有可能是别人抢到了，也有可能他自己有抢到了。我们还知道线程有个优先级的问题，
     * 那么手里有优先权的这些人就一定能抢到厕所的位置吗? 不一定的，他们只是概率上大些，也有可能没特权的抢到了。
     */
    public static void main(String[] args) {
        new YieldTest("张三").start();
        new YieldTest("李四").start();
    }

    public static void main1(String[] args) throws InterruptedException {
        var ex = new _47_join_yield();
        // 开启了四个线程  每个线程循环打印5次名字
        var t1 = new Thread(ex::workJoin, "T1");
        var t2 = new Thread(ex::workJoin, "T2");
        var t3 = new Thread(ex::workJoin, "T3");
        var t4 = new Thread(ex::workJoin, "T4");
        //并行
        //t2->t3 串行执行
        //t1->t3 串行执行 先执行t1再执行t3
        t1.start();
        t2.start();
        t1.join();
        //① t1 t2 交替... 当t1线程执行完后开始t3线程，执行过程中和t2没有关系

        t3.start();
        t2.join();
        //② t2 t3 交替执行..当t2线程执行完后开始t4线程，执行过程中和t3没有关系
        //      但是 t2 在前两个线程的时候就已经执行完毕 则t3 t4 交替执行

        t4.start();


        // 将异常抛出去  不处理(仅为测试)
    }

    /**
     * 线程进行循环5次打印线程名字  每隔1秒
     */
    void workJoin() {
        String tn = Thread.currentThread().getName();
        for (int i = 0; i < 5; i++) {
            try {
                TimeUnit.SECONDS.sleep(1);
            } catch (Exception e) {
                e.printStackTrace();
            }
            System.out.printf("%s = %d%n", tn, i);
        }
    }

    static class YieldTest extends Thread {
        public YieldTest(String name) {
            super(name);
        }

        @Override
        public void run() {
            for (int i = 0; i < 8; i++) {
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("" + this.getName() + "-----" + i);
                // 当i为5时，该线程就会把CPU时间让掉，让其他或者自己的线程执行（也就是谁先抢到谁执行）
                if (i == 5) {
                    System.out.println(Thread.currentThread().getName() + "  我让了");
                    Thread.yield();
                }
            }
        }
    }
}


